import { isDev } from '@/config/EnvironmentVariable.ts'
import { AuthenticationInterceptor, AuthenticationRefreshInterceptor } from '@/config/httpClient/AuthenticationInterceptor.ts'
import { GeneralErrorProcessor } from '@/config/httpClient/GeneralErrorProcessor.ts'
import type { HttpClient } from '@/config/httpClient/HttpClient.ts'
import { QueryParameterEncodingInterceptor } from '@/config/httpClient/QueryParameterEncodingInterceptor.ts'
import { httpClient } from '@/config/index.ts'
import { RouteDefinition } from '@/config/router/RouteDefinition.ts'
import { RouterGuardManager } from '@/config/router/RouterGuardManager.ts'
import { PageAuthentication, RouteNavigationLog, SetPageTitleRouterGuard } from '@/config/router/SimpleRouterGuard.ts'
import { AccountSettingService } from '@/config/service/AccountSettingService.ts'
import { SiteGroupService } from '@/config/service/SiteGroupService.ts'
import { PersistencePlugin } from '@/config/store/PersistencePlugin.ts'
import AppComponent from '@/page/App.vue'
import ArcoVue, { Message } from '@arco-design/web-vue'
import ArcoVueIcon from '@arco-design/web-vue/es/icon'
import { createPinia, type Pinia } from 'pinia'
import { type App, createApp } from 'vue'
import { createRouter, createWebHistory, type Router } from 'vue-router'

/**
 * 主应用
 */
export class TianShuStartApplication {

    /**
     * Vue 实例
     */
    public readonly vueInstance: App<Element>

    /**
     * VueRouter 实例
     */
    public readonly vueRouter: Router

    /**
     * VueRouter 导航守卫管理器
     */
    public readonly routerGuardManager: RouterGuardManager

    /**
     * pinia 实例
     */
    public readonly pinia: Pinia

    /**
     * HTTP Client
     */
    public readonly httpClient: HttpClient

    public readonly siteGroupService: SiteGroupService = new SiteGroupService()

    public readonly accountSettingService: AccountSettingService = new AccountSettingService()

    /**
     * 构造
     *
     * 初始化应用, 定义安装顺序
     */
    public constructor() {
        this.httpClient = httpClient
        // 注册请求响应拦截器
        this.initHttpClient()

        this.vueInstance = createApp(AppComponent)

        // 初始化组件库
        this.vueInstance.use(ArcoVue)
        this.vueInstance.use(ArcoVueIcon)
        Message._context = this.vueInstance._context

        // 初始化路由, 注册导航守卫
        this.vueRouter = createRouter({
            history: createWebHistory(),
            routes: RouteDefinition,
        })
        this.routerGuardManager = new RouterGuardManager(this.vueRouter)
        this.initVueRouter()
        this.vueInstance.use(this.vueRouter)

        // 初始化 Pinia
        this.pinia = this.initPinia()
        this.vueInstance.use(this.pinia)

        this.vueInstance.config.globalProperties.$application = this
    }

    public start(): void {
        this.vueInstance.mount('#app')
    }

    private initVueRouter(): void {
        if (isDev()) {
            this.routerGuardManager.beforeEach('记录导航日志', RouteNavigationLog)
        }
        this.routerGuardManager.beforeEach('页面鉴权', PageAuthentication)
        this.routerGuardManager.afterEach('设置页面标题', SetPageTitleRouterGuard)
    }

    private initPinia(): Pinia {
        const pinia = createPinia()
        pinia.use(PersistencePlugin)

        return pinia
    }

    private initHttpClient(): void {
        const manager = this.httpClient.interceptorManager
        manager.addRequestInterceptor(new QueryParameterEncodingInterceptor(), '请求参数编码')
        manager.addRequestInterceptor(new AuthenticationInterceptor(), '附加认证请求头拦截器')

        manager.addResponseInterceptor(new AuthenticationRefreshInterceptor(this.httpClient, () => this.vueRouter), '身份验证刷新拦截器')
        manager.addResponseInterceptor(new GeneralErrorProcessor(), '通用错误处理')
    }

}
